package org.dru.masic.testapp {
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.events.UncaughtErrorEvent;
	import flash.text.TextField;
	
	import org.dru.masic.MasicPlayer;
	import org.dru.masic.effects.crossdelay.CrossDelay;
	import org.dru.masic.effects.reverb.Reverb;
	import org.dru.masic.sequencers.tracker.Tracker;
	import org.dru.masic.synths.flute.Flute;
	import org.dru.masic.synths.kick.Kick;
	import org.dru.masic.synths.sawer.Sawer;
	import org.dru.masic.utils.ILoggerOutput;
	import org.dru.masic.utils.Logger;
	
	[SWF(width="640", height="480", scaleMode="noScale", frameRate="60")]
	public class Masic extends Sprite implements ILoggerOutput {
	    private static var _logs: Vector.<String>;
	    private static var _textField: TextField;
	    private var _tracker: Tracker;
	    private var _player: MasicPlayer;
	    //
	    private var _sawer1: Flute;
	    private var _flute: Sawer;
	    private var _kick: Kick;
	    private var _delay: CrossDelay;
	    private var _reverb: Reverb;
	
	    public function Masic() {
	        _logs = new Vector.<String>();
	        _textField = new TextField();
	        _textField.multiline = true;
	        _textField.width = 640;
	        _textField.height = 480;
	        addChild(_textField);
	        //
	        addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
			
			Logger.registerOutput(this, Logger.DEBUG);
	    }
	
		public function print(logLevel:int, logMessage:String): void {
			_logs.push(logMessage);
			if (_logs.length > 32) {
				_logs.splice(0, 1);
			}
			_textField.text = "";
			for each (var log: String in _logs) {
				_textField.appendText(log + "\n");
			}
		}
		
	    private function onAddedToStage(event: Event): void {
	        removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
	        addEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage);
	        //
	        loaderInfo.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, onUncaughtError);
	        //
	        _tracker = new Tracker();
	        _player = new MasicPlayer();
	        _player.sequencer = _tracker; // this makes the player start sound
	        //
	        _sawer1 = new Flute();
	        _sawer1.getParameterAt(0).value = 0.01;
	        _sawer1.getParameterAt(1).value = 0.125;
	        _sawer1.getParameterAt(2).value = 0.0;
	        _sawer1.getParameterAt(3).value = 0.0;
	        //
	        _flute = new Sawer();
	        _flute.getParameterAt(0).value = 0.5;
	        _flute.getParameterAt(1).value = 0.5;
	        _flute.getParameterAt(2).value = 0.0;
	        _flute.getParameterAt(3).value = 0.0;
	        //
	        _kick = new Kick();
	        //
	        _delay = new CrossDelay();
	        //
	        _reverb = new Reverb();
	        //
	        _tracker.container.addComponent(_sawer1);
	        _tracker.container.addComponent(_flute);
	        _tracker.container.addComponent(_kick);
	        _tracker.container.addComponent(_delay);
	        _tracker.container.addComponent(_reverb);
	        //
	        _sawer1.getOutputAt(0).addTarget(_delay.getInputAt(0));
	        _flute.getOutputAt(0).addTarget(_tracker.container.speaker.getInputAt(0));
	        _kick.getOutputAt(0).addTarget(_tracker.container.speaker.getInputAt(0));
	        _delay.getOutputAt(0).addTarget(_reverb.getInputAt(0));
	        _reverb.getOutputAt(0).addTarget(_tracker.container.speaker.getInputAt(0));
	        // song
	        _tracker.song.addSequenceEntry(0);
	        _tracker.song.addPattern(64);
	        // pattern 0, track 0
	        _tracker.song.addNoteTrack();
	        _tracker.song.setNoteEntry(0, 0, 0, 0x29000000);
	        _tracker.song.setNoteEntry(0, 0, 2, 0x30008000);
	        _tracker.song.setNoteEntry(0, 0, 4, 0x30000000);
	        _tracker.song.setNoteEntry(0, 0, 6, 0x30008000);
	        _tracker.song.setNoteEntry(0, 0, 8, 0x30000000);
	        _tracker.song.setNoteEntry(0, 0, 10, 0x30008000);
	        _tracker.song.setNoteEntry(0, 0, 12, 0x30000000);
	        _tracker.song.setNoteEntry(0, 0, 14, 0x30008000);
	        _tracker.song.setNoteEntry(0, 0, 16, 0x30000000);
	        _tracker.song.setNoteEntry(0, 0, 18, 0x2b008000);
	        _tracker.song.setNoteEntry(0, 0, 20, 0x2b000000);
	        _tracker.song.setNoteEntry(0, 0, 22, 0x2b008000);
	        _tracker.song.setNoteEntry(0, 0, 24, 0x2b000000);
	        _tracker.song.setNoteEntry(0, 0, 26, 0x2b008000);
	        _tracker.song.setNoteEntry(0, 0, 28, 0x2b000000);
	        _tracker.song.setNoteEntry(0, 0, 30, 0x2b008000);
	        _tracker.song.setNoteEntry(0, 0, 32, 0x2b000000);
	        _tracker.song.setNoteEntry(0, 0, 34, 0x2c008000);
	        _tracker.song.setNoteEntry(0, 0, 36, 0x2c000000);
	        _tracker.song.setNoteEntry(0, 0, 38, 0x2c008000);
	        _tracker.song.setNoteEntry(0, 0, 40, 0x2c000000);
	        _tracker.song.setNoteEntry(0, 0, 42, 0x2c008000);
	        _tracker.song.setNoteEntry(0, 0, 44, 0x2c000000);
	        _tracker.song.setNoteEntry(0, 0, 46, 0x2c008000);
	        _tracker.song.setNoteEntry(0, 0, 48, 0x2c000000);
	        _tracker.song.setNoteEntry(0, 0, 50, 0x29008000);
	        _tracker.song.setNoteEntry(0, 0, 52, 0x29000000);
	        _tracker.song.setNoteEntry(0, 0, 54, 0x29008000);
	        _tracker.song.setNoteEntry(0, 0, 56, 0x29000000);
	        _tracker.song.setNoteEntry(0, 0, 58, 0x29008000);
	        _tracker.song.setNoteEntry(0, 0, 60, 0x29000000);
	        _tracker.song.setNoteEntry(0, 0, 62, 0x29008000);
	        // pattern 0, track 1
	        _tracker.song.addNoteTrack();
	        _tracker.song.setNoteEntry(1, 0, 0, 0x48012000);
	        _tracker.song.setNoteEntry(1, 0, 1, 0x4b012000);
	        _tracker.song.setNoteEntry(1, 0, 32, 0x48010000);
	        _tracker.song.setNoteEntry(1, 0, 33, 0x4b010000);
	        // pattern 0, track 2
	        _tracker.song.addNoteTrack();
	        _tracker.song.setNoteEntry(2, 0, 0, 0x00028000);
	        _tracker.song.setNoteEntry(2, 0, 4, 0x00028000);
	        _tracker.song.setNoteEntry(2, 0, 8, 0x00028000);
	        _tracker.song.setNoteEntry(2, 0, 12, 0x00028000);
	        _tracker.song.setNoteEntry(2, 0, 16, 0x00028000);
	        _tracker.song.setNoteEntry(2, 0, 20, 0x00028000);
	        _tracker.song.setNoteEntry(2, 0, 24, 0x00028000);
	        _tracker.song.setNoteEntry(2, 0, 28, 0x00028000);
	        _tracker.song.setNoteEntry(2, 0, 32, 0x00028000);
	        _tracker.song.setNoteEntry(2, 0, 36, 0x00028000);
	        _tracker.song.setNoteEntry(2, 0, 40, 0x00028000);
	        _tracker.song.setNoteEntry(2, 0, 44, 0x00028000);
	        _tracker.song.setNoteEntry(2, 0, 48, 0x00028000);
	        _tracker.song.setNoteEntry(2, 0, 52, 0x00028000);
	        _tracker.song.setNoteEntry(2, 0, 56, 0x00028000);
	        _tracker.song.setNoteEntry(2, 0, 60, 0x00028000);
	        _tracker.song.setNoteEntry(2, 0, 62, 0x00025000);
	        // automation
	        _tracker.song.addTweakTrack(0, 4);
	        for (var line: int = 0; line < 65; line++) {
	            _tracker.song.setTweakEntry(0, 0, line, line);
	        }
	        //
	        addEventListener(KeyboardEvent.KEY_DOWN, function (event: KeyboardEvent): void {
	            _tracker.playing = !_tracker.playing;
	        });
	        //
	        Logger.log(Logger.INFO, "press any key to toggle music");
	        trace(JSON.stringify(_tracker.container.encode()));
	    }
	
	    private function onRemovedFromStage(event: Event): void {
	        _player.sequencer = null;
	        removeEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage);
	        removeChild(_textField);
	        loaderInfo.uncaughtErrorEvents.removeEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, onUncaughtError);
	    }
	
		private static function onUncaughtError(event: UncaughtErrorEvent): void {
	       Logger.log(Logger.ERROR, event.error);
	    }
	}
}
